﻿using BCCommon;
using BCData.TMS.Agent.AgentBranchesConfig;
using BCDto.Location.Branches;
using BCDto.Sim.Admin.Admin;
using BCDto.TMS.Agent.AgentBranchesConfig;
using BCEntity.Common.EntityNameConst;
using BCEntity.TMS.Agent.AgentBranchesConfig;
using BCMongoData.TMS.Location.Branches;
using BCMongoEntity.TMS.Location.Branches;
using BCService.Common.Area;
using BCService.Utils;
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCService.TMS.Agent.AgentBranchesConfig
{
    public class AgentBranchesConfigService : IAgentBranchesConfigService
    {
        private readonly IAgentBranchesConfigData agentBranchesConfigData;
        private readonly IRedisService redisService;
        private readonly IZoneService zoneService;
        private readonly IBranchesLocationMongoData branchesLocationMongoData;
        private readonly string key = string.Format("{0}", EntityNameConst.AgentBranchesConfigEntity);

        public AgentBranchesConfigService(IAgentBranchesConfigData agentBranchesConfigData,
            IRedisService redisService,
            IZoneService zoneService,
            IBranchesLocationMongoData branchesLocationMongoData)
        {
            this.agentBranchesConfigData = agentBranchesConfigData;
            this.redisService = redisService;
            this.zoneService = zoneService;
            this.branchesLocationMongoData = branchesLocationMongoData;
        }

        public AgentBranchesConfigDto Add(AdminDto admin, AgentBranchesConfigRequestDto dto)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException("非代理商不能添加网点配置");
            }
            var zoneEntity = this.zoneService.GetFromZoneEntity(dto.CountyCode);
            if (zoneEntity == null || zoneEntity.countyEntity == null || zoneEntity.provinceEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("区县编码不存在!");
            }
            var result = this.agentBranchesConfigData.Insert(new AgentBranchesConfigEntity()
            {
                AgentBranchesName = dto.AgentBranchesName,
                AgentRecordId = admin.AgentRecord.AgentRecordId,
                ContactPhone = dto.ContactPhone,
                ProvinceCode = zoneEntity.provinceEntity.ProvinceCode,
                ProvinceName = zoneEntity.provinceEntity.ProvinceName,
                CityCode = zoneEntity.cityEntity.CityCode,
                CityName = zoneEntity.cityEntity.CityName,
                CountyCode = zoneEntity.countyEntity.CountyCode,
                CountyName = zoneEntity.countyEntity.CountyName,
                Longitude = dto.Longitude,
                Latitude = dto.Latitude,
                Address = dto.Address,
                IsSend = dto.IsSend,
                IsReceive = dto.IsReceive,
                Remark = dto.Remark,
                CreateTime = DateTime.Now,
                UpdateTime = DateTime.Now
            }).GetAwaiter().GetResult();
            BranchesLocationEntity entity = new BranchesLocationEntity()
            {
                AgentBranchesConfigId = result.AgentBranchesConfigId,
                AgentBranchesName = result.AgentBranchesName,
                Longitude = dto.Longitude,
                Latitude = dto.Latitude,
                Coordinate = new double[] { Math.Round(dto.Longitude, 8), Math.Round(dto.Latitude, 8) },
                IsSend = dto.IsSend,
                IsReceive = dto.IsReceive
            };
            this.branchesLocationMongoData.Insert(entity);
            this.redisService.DeleteMultipleKey(key, false);
            return result.As<AgentBranchesConfigDto>();
        }

        public void Delete(AdminDto admin, long agentBranchesConfigId)
        {
            var result = this.agentBranchesConfigData.GetById(agentBranchesConfigId).Result;
            if (result == null)
            {
                throw new ArgumentException("代理商网点配置信息不存在");
            }
            if (admin.AgentRecord != null && admin.AgentRecord.AgentRecordId != result.AgentRecordId)
            {
                throw new ArgumentException("您暂无权限删除此信息");
            }
            this.agentBranchesConfigData.Delete(agentBranchesConfigId).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
            this.branchesLocationMongoData.Delete(agentBranchesConfigId);
        }

        public AgentBranchesConfigDto GetById(long agentBranchesConfigId)
        {
            var result = this.agentBranchesConfigData.GetById(agentBranchesConfigId).Result;
            return result.As<AgentBranchesConfigDto>();
        }

        public IEnumerable<BranchesLocationNearDto> GetList(double longitude, double latitude, int maxDistance)
        {
            double[] location = new double[2] { Math.Round(longitude, 8), Math.Round(latitude, 8) };

            List<BsonElement> projections = new List<BsonElement>
            {
                new BsonElement("AgentBranchesConfigId", 1),
                new BsonElement("AgentBranchesName", 1),
                new BsonElement("Longitude", 1),
                new BsonElement("Latitude", 1),
                new BsonElement("IsSend",1),
                new BsonElement("IsReceive",1)
            };
            IEnumerable<BranchesLocationNearEntity> locationDriverNearEntitys = this.branchesLocationMongoData.GetGeoNearLocationsByCoordinate(location, maxDistance, null, null);
            return locationDriverNearEntitys.As<IEnumerable<BranchesLocationNearDto>>();
        }

        public PageableList<AgentBranchesConfigDto> Query(AdminDto admin, string agentBranchesName, string contactPhone, string provinceCode, string cityCode, string countyCode, string address, int pageIndex, int pageSize)
        {
            string cacheKey = this.redisService.GetKey(key, admin.AgentRecord?.AgentRecordId, agentBranchesName, contactPhone, provinceCode, cityCode, countyCode, address, pageIndex, pageSize);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var (data, dataCount) = this.agentBranchesConfigData.Query(admin.AgentRecord?.AgentRecordId, agentBranchesName, contactPhone, provinceCode, cityCode, countyCode, address, pageIndex, pageSize).Result;
                return new PageableList<AgentBranchesConfigDto>()
                {
                    Count = dataCount,
                    Items = data.As<List<AgentBranchesConfigDto>>(),
                    PageIndex = pageIndex,
                    PageSize = pageSize
                };
            }, TimeSpan.FromDays(1));
            return result;
        }

        public AgentBranchesConfigDto Update(AdminDto admin, long agentBranchesConfigId, AgentBranchesConfigRequestDto dto)
        {
            var result = this.agentBranchesConfigData.GetById(agentBranchesConfigId).Result;
            if (result == null)
            {
                throw new ArgumentException("代理商网点配置信息不存在");
            }
            if (admin.AgentRecord != null && admin.AgentRecord.AgentRecordId != result.AgentRecordId)
            {
                throw new ArgumentException("您暂无权限修改此信息");
            }
            var zoneEntity = this.zoneService.GetFromZoneEntity(dto.CountyCode);
            if (zoneEntity == null || zoneEntity.countyEntity == null || zoneEntity.provinceEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("区县编码不存在!");
            }
            result.AgentBranchesName = dto.AgentBranchesName;
            result.ContactPhone = dto.ContactPhone;
            result.ProvinceCode = zoneEntity.provinceEntity.ProvinceCode;
            result.ProvinceName = zoneEntity.provinceEntity.ProvinceName;
            result.CityCode = zoneEntity.cityEntity.CityCode;
            result.CityName = zoneEntity.cityEntity.CityName;
            result.CountyCode = zoneEntity.countyEntity.CountyCode;
            result.CountyName = zoneEntity.countyEntity.CountyName;
            result.Longitude = dto.Longitude;
            result.Latitude = dto.Latitude;
            result.Address = dto.Address;
            result.IsSend = dto.IsSend;
            result.IsReceive = dto.IsReceive;
            result.Remark = dto.Remark;
            result.UpdateTime = DateTime.Now;
            this.agentBranchesConfigData.Update(result).GetAwaiter().GetResult();
            BranchesLocationEntity entity = new BranchesLocationEntity()
            {
                AgentBranchesConfigId = result.AgentBranchesConfigId,
                AgentBranchesName = result.AgentBranchesName,
                Longitude = dto.Longitude,
                Latitude = dto.Latitude,
                Coordinate = new double[] { Math.Round(dto.Longitude, 8), Math.Round(dto.Latitude, 8) },
                IsSend = dto.IsSend,
                IsReceive = dto.IsReceive
            };
            this.branchesLocationMongoData.Update(entity);
            this.redisService.DeleteMultipleKey(key, false);
            return result.As<AgentBranchesConfigDto>();
        }
    }
}
